/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Juego;

import Controlador.Controlador;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

/**
 *
 * @author Flor
 */
public class Mesa extends Observable {

    private static Mesa instancia;

    public static Mesa darInstancia() {
        if (instancia == null) {
            instancia = new Mesa();
        }
        return instancia;
    }
    private List<Jugador> lstJugadores = new ArrayList();
    private Integer pozo = 0;
    private List<Carta> lstCartas = new ArrayList();
    private Mazo mazo;
    private Jugador ultimoAp;

    //GETTERS AND SETTERS
    public List<Carta> getLstCartas() {
        return lstCartas;
    }

    public void setLstCartas(List<Carta> lstCartas) {
        this.lstCartas = lstCartas;
        this.setChanged();
        this.notifyObservers("CartasMesa");
    }

    public List<Jugador> getLstJugadores() {
        return lstJugadores;
    }

    public void setLstJugadores(List<Jugador> lstJugadores, int metodo) {

        this.lstJugadores = lstJugadores;
        this.setChanged();
        if (metodo == 0) {
            this.notifyObservers("lstJugadores");
        } else if (metodo == 1) {
            this.notifyObservers("mostrarCartas");
        } else if (metodo == 2) {
            this.notifyObservers("ocultarCartas");
        }

    }

    public Mazo getMazo() {
        return mazo;
    }

    public void setMazo(Mazo mazo) {
        this.mazo = mazo;
        this.setChanged();
        this.notifyObservers("mazo");

    }

    public Integer getPozo() {
        return pozo;
    }

    public void setPozo(Integer pozo) {
        this.pozo = pozo;
        this.setChanged();
        this.notifyObservers("pozo");

    }

    public Jugador getUltimoAp() {
        return ultimoAp;
    }

    public void setUltimoAp(Jugador ultimoAp) {
        this.ultimoAp = ultimoAp;

    }
    //FIN GETTERS AND SETTERS

    private Mesa() {
    }

    public boolean agregarJugador(Jugador jugador) {
        try {
            List<Jugador> lstAux = getLstJugadores();
            lstAux.add(jugador);
            setLstJugadores(lstAux, 0);//lo seteo para notificar cambios
            return true;

        } catch (Exception e) {
            return false;
        }
    }

    public Jugador buscarDealer()//busca el dealer de la mesa
    {
        Jugador jugAux = null;
        int i = 0;
        while (i < getLstJugadores().size()) {
            if (getLstJugadores().get(i).isDealer()) {
                jugAux = getLstJugadores().get(i);
            }
            i++;
        }
        return jugAux;
    }

    public void apostarCiega(Jugador jugador, int monto)//realiza una apuesta
    {
        try {
            jugador.apostarCiega(monto);
            setLstJugadores(getLstJugadores(), 0);
            setPozo(getPozo() + monto);//aumento el pozo

            if (getUltimoAp() == null) {
                setUltimoAp(jugador);
            } else if (getUltimoAp() != null && monto > getUltimoAp().getuApuesta())//si la apuesta es mayor lo declara como el ultimo apostador
            {
                setUltimoAp(jugador);
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public void chekarPrestamos() {
        List<Jugador> lstAux = this.getLstJugadores();
        Jugador jugAux = null;

        for (int i = 0; i < lstAux.size(); i++) {


            jugAux = lstAux.get(i);

            if (jugAux.getMontoDisponible() <= 0 && !jugAux.isPrestamoActivo()) {

                if (jugAux.esHumano()) {

                    boolean confirmado = Controlador.darInstancia().confirmarPrestamo();

                    if (confirmado == true) {
                        jugAux.setMontoDisponible(jugAux.getMontoDisponible() + 100);
                        jugAux.setPrestamoActivo(true);
                        jugAux.setActivo(true);
                    }

                } else {
                    jugAux.setMontoDisponible(jugAux.getMontoDisponible() + 100);
                    jugAux.setPrestamoActivo(true);
                    jugAux.setActivo(true);
                }
            }

        }

    }

    public boolean apostar(Jugador jugador, int monto)//devuelve verdadero si le alcanza el monto al jugador y realiza la apuesta
    {
        try {

            boolean res = false;
            if (jugador.getMontoDisponible() - monto >= 0) {
                res = jugador.apostar(monto);
                setPozo(getPozo() + monto);//aumento el pozo

            }

            setLstJugadores(lstJugadores, 0);


            return res;

        } catch (Exception e) {
            return false;
        }
    }

    public Jugador buscarUltimoActivo() {
        Jugador jugAux = new Jugador();
        for (int i = 0; i < getLstJugadores().size(); i++) {
            if (getLstJugadores().get(i).isActivo()) {
                jugAux = getLstJugadores().get(i);
            }
        }
        return jugAux;
    }

    public int cantAllIn() {

        int cant = 0;

        for (int k = 0; k < this.getLstJugadores().size(); k++) {
            if (this.getLstJugadores().get(k).isAllIn()) {
                cant++;
            }
        }
        return cant;

    }

    public int cantActivos()//devuelve la cantidad de jugadores activos
    {
        int cant = 0;
        for (int k = 0; k < this.getLstJugadores().size(); k++) {
            if (this.getLstJugadores().get(k).isActivo()) {
                cant++;
            }
        }
        return cant;
    }

    public int cantFuera()//devuleve los jugadores q ya no estan jugando en la partida
    {
        int cant = 0;
        for (int k = 0; k < this.getLstJugadores().size(); k++) {
            if (this.getLstJugadores().get(k).isSigueEnLaPartida()) {
                cant++;
            }
        }
        return cant;
    }

    public Jugador buscarSiguienteActivo(Jugador jugAux) {

        Jugador res = jugAux.getSigJugador();

        while (true) {
            if (res.isActivo() == true) {
                return res;

            } else if (res.getNombre().equals(ultimoAp.getNombre())) {

                return res;
            } else {

                res = res.getSigJugador();
            }


        }



    }

    public void repartirCartasJugador(Jugador dealer, int cantidad)//reparte N cartas a los jugadores
    {
        try {
            Jugador jugAux = dealer;
            boolean terminado = false;


            List<Carta> auxLst = new ArrayList<>();

            while (terminado == false) {
                for (int i = 0; i < cantidad; i++) {
                    auxLst.add(getMazo().getLstCartas().get(0));//obtengo la primera carta del mazo
                    getMazo().getLstCartas().remove(0);
                }

                if (jugAux.getSigJugador() != null) {
                    asignarCartas(auxLst, jugAux.getSigJugador().getNombre());
                }

                auxLst.removeAll(auxLst);

                if (jugAux.getSigJugador() != null && jugAux.getSigJugador().isDealer() == true) {
                    terminado = true;
                    this.setLstJugadores(this.lstJugadores, 0);
                }

                jugAux = jugAux.getSigJugador();//setea a jug el siguiente jugador
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public boolean asignarCartas(List<Carta> lstAux, String nombre)//establece las cartas del mazo en la lista de cartas del jugador
    {
        for (int i = 0; i < getLstJugadores().size(); i++) {

            if (getLstJugadores().get(i).getNombre().equals(nombre))//pregunta si el jugador de la lista es igual al q se le paso al metodo
            {
                List<Carta> lstCar = new ArrayList<>();
                for (int j = 0; j < lstAux.size(); j++) {
                    Carta caraux1 = new Carta(lstAux.get(j).getNumero(), lstAux.get(j).getPalo());
                    lstCar.add(caraux1);
                }
                List<Jugador> lstJugAux = getLstJugadores();
                lstJugAux.get(i).setLstCartas(lstCar);
                setLstJugadores(lstJugAux, 0);


                return true;
            }


        }

        return false;
    }

    public void cambiarDealer(Jugador sigJugador)//Asigna el cargo de dealer a un jugador y notifica a los observadores
    {
        try {
            sigJugador.setDealer(true);
            this.setChanged();
            this.notifyObservers("dealer");
        } catch (Exception e) {
        }

    }

    public boolean repartirCartasMesa(int n)//pone n cartas en la mesa
    {
        try {
            List<Carta> lstAux = getLstCartas();
            for (int i = 0; i < n; i++) {

                lstAux.add(getMazo().getLstCartas().get(i));//obtengo la primera carta del mazo
                getMazo().getLstCartas().remove(i);//la elimino del maso
                // setLstCartas(lstAux);
            }
            setLstCartas(lstAux);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public void mostrarCartas() {
        try {
            setLstJugadores(this.getLstJugadores(), 1);

        } catch (Exception e) {
        }

    }

    public void ocultarCartas() {
        try {
            setLstJugadores(this.getLstJugadores(), 2);
        } catch (Exception e) {
        }

    }

    public void activarJugadores() {
        List<Jugador> lstAux = this.getLstJugadores();
        for (int i = 0; i < lstAux.size(); i++) {

            if (lstAux.get(i).getMontoDisponible() > 0) {
                lstAux.get(i).setActivo(true);
            }

        }

    }
}
